package com.wxlalt.rediscache.config;

import cn.hutool.core.util.StrUtil;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * @author a1615
 */
public interface VersionCall {


    default <T> T getServerOrDefaultByVersion(T[] servers, String version) {
        AtomicReference<T> defaultT = new AtomicReference<>();
        AtomicReference<T> havVersionT = new AtomicReference<>();
        List<T> filterServe ;
         Stream.of(servers)
                .filter(item -> {
                    Version annotation = AnnotationUtils.findAnnotation(item.getClass(), Version.class);
                    return annotation != null && (
                            (
                                    !StrUtil.isBlank(annotation.version()) && annotation.version().equals(version)
                            )
                                    || annotation.isDefault()
                    );
                })
                 .forEach(item->{
                     Version annotation = AnnotationUtils.findAnnotation(item.getClass(), Version.class);
                     Optional.ofNullable(annotation).ifPresent(ann->{
                         if(ann.isDefault())
                             defaultT.set(item);
                         else if(!StrUtil.isBlank(version)&&version.equals(ann.version()))
                             havVersionT.set(item);
                     });
                 });

         return havVersionT.get()==null?defaultT.get():havVersionT.get();
    }

    default <T> T getServerByVersion(T[] servers, String version) {
        List<T> filterServe = Stream.of(servers)
                .filter(item -> {
                    Version annotation = AnnotationUtils.findAnnotation(item.getClass(), Version.class);
                    return annotation != null
                            && !StrUtil.isBlank(annotation.version())
                            && annotation.version().equals(version);
                })
                .collect(Collectors.toList());


        return filterServe.size() > 0 ? filterServe.get(0) : null;
    }

    default <T> T getServerByDefalit(T[] servers) {
        List<T> filterServe = Stream.of(servers)
                .filter(item -> {
                    Version annotation = AnnotationUtils.findAnnotation(item.getClass(), Version.class);
                    return annotation != null
                            && annotation.isDefault();
                })
                .collect(Collectors.toList());


        return filterServe.size() > 0 ? filterServe.get(0) : null;
    }


    @Documented
    @Retention(RUNTIME)
    @Target(value = {TYPE})
    public @interface Version {
        boolean isDefault() default false;

        @AliasFor("version")
        String value() default StrUtil.EMPTY;

        @AliasFor("value")
        String version() default StrUtil.EMPTY;
    }

}
